/*
 *  webui popover plugin  - v1.2.17
 *  A lightWeight popover plugin with jquery ,enchance the  popover plugin of bootstrap with some awesome new features. It works well with bootstrap ,but bootstrap is not necessary!
 *  https://github.com/sandywalker/webui-popover
 *
 *  Made by Sandy Duan
 *  Under MIT License
 */

layui.define(["jquery", "element"], function (exports) {
  var $ = layui.$;
  // Create the defaults once
  var pluginName = "webuiPopover";
  var pluginClass = "webui-popover";
  var pluginType = "webui.popover";
  var defaults = {
    placement: "auto",
    container: null,
    width: "auto",
    height: "auto",
    trigger: "click", //hover,click,sticky,manual
    style: "",
    opacity: null,
    selector: false, // jQuery selector, if a selector is provided, popover objects will be delegated to the specified.
    delay: {
      show: null,
      hide: 300,
    },
    async: {
      type: "GET",
      before: null, //function(that, xhr, settings){}
      success: null, //function(that, xhr){}
      error: null, //function(that, xhr, data){}
    },
    cache: true,
    multi: false,
    arrow: true,
    title: "",
    content: "",
    closeable: false,
    padding: true,
    url: "",
    type: "html",
    direction: "", // ltr,rtl
    animation: null,
    template:
      '<div class="webui-popover">' +
      '<div class="webui-arrow"></div>' +
      '<div class="webui-popover-inner">' +
      '<a href="#" class="close"></a>' +
      '<h3 class="webui-popover-title"></h3>' +
      '<div class="webui-popover-content"><i class="icon-refresh"></i> <p>&nbsp;</p></div>' +
      "</div>" +
      "</div>",
    backdrop: false,
    dismissible: true,
    onShow: null,
    onHide: null,
    abortXHR: true,
    autoHide: false,
    offsetTop: 0,
    offsetLeft: 0,
    iframeOptions: {
      frameborder: "0",
      allowtransparency: "true",
      id: "",
      name: "",
      scrolling: "",
      onload: "",
      height: "",
      width: "",
    },
    hideEmpty: false,
  };

  var rtlClass = pluginClass + "-rtl";
  var _srcElements = [];
  var backdrop = $('<div class="webui-popover-backdrop"></div>');
  var _globalIdSeed = 0;
  var _isBodyEventHandled = false;
  var _offsetOut = -2000; // the value offset  out of the screen
  var $document = $(document);

  var toNumber = function (numeric, fallback) {
    return isNaN(numeric) ? fallback || 0 : Number(numeric);
  };

  var getPopFromElement = function ($element) {
    return $element.data("plugin_" + pluginName);
  };

  var hideAllPop = function () {
    var pop = null;
    for (var i = 0; i < _srcElements.length; i++) {
      pop = getPopFromElement(_srcElements[i]);
      if (pop) {
        pop.hide(true);
      }
    }
    $document.trigger("hiddenAll." + pluginType);
  };

  var hideOtherPops = function (currentPop) {
    var pop = null;
    for (var i = 0; i < _srcElements.length; i++) {
      pop = getPopFromElement(_srcElements[i]);
      if (pop && pop.id !== currentPop.id) {
        pop.hide(true);
      }
    }
    $document.trigger("hiddenAll." + pluginType);
  };

  var isMobile =
    "ontouchstart" in document.documentElement &&
    /Mobi/.test(navigator.userAgent);

  var pointerEventToXY = function (e) {
    var out = {
      x: 0,
      y: 0,
    };
    if (
      e.type === "touchstart" ||
      e.type === "touchmove" ||
      e.type === "touchend" ||
      e.type === "touchcancel"
    ) {
      var touch =
        e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
      out.x = touch.pageX;
      out.y = touch.pageY;
    } else if (
      e.type === "mousedown" ||
      e.type === "mouseup" ||
      e.type === "click"
    ) {
      out.x = e.pageX;
      out.y = e.pageY;
    }
    return out;
  };

  // The actual plugin constructor
  function WebuiPopover(element, options) {
    this.$element = $(element);
    if (options) {
      if (
        $.type(options.delay) === "string" ||
        $.type(options.delay) === "number"
      ) {
        options.delay = {
          show: options.delay,
          hide: options.delay,
        }; // bc break fix
      }
    }
    this.options = $.extend({}, defaults, options);
    this._defaults = defaults;
    this._name = pluginName;
    this._targetclick = false;
    this.init();
    _srcElements.push(this.$element);
    return this;
  }

  WebuiPopover.prototype = {
    //init webui popover
    init: function () {
      if (
        this.$element[0] instanceof document.constructor &&
        !this.options.selector
      ) {
        throw new Error(
          "`selector` option must be specified when initializing " +
            this.type +
            " on the window.document object!"
        );
      }

      if (this.getTrigger() !== "manual") {
        //init the event handlers
        if (isMobile) {
          this.$element
            .off("touchend", this.options.selector)
            .on("touchend", this.options.selector, $.proxy(this.toggle, this));
        } else if (this.getTrigger() === "click") {
          this.$element
            .off("click", this.options.selector)
            .on("click", this.options.selector, $.proxy(this.toggle, this));
        } else if (this.getTrigger() === "hover") {
          this.$element
            .off("mouseenter mouseleave click", this.options.selector)
            .on(
              "mouseenter",
              this.options.selector,
              $.proxy(this.mouseenterHandler, this)
            )
            .on(
              "mouseleave",
              this.options.selector,
              $.proxy(this.mouseleaveHandler, this)
            );
        }
      }
      this._poped = false;
      this._inited = true;
      this._opened = false;
      this._idSeed = _globalIdSeed;
      this.id = pluginName + this._idSeed;
      // normalize container
      this.options.container = $(
        this.options.container || document.body
      ).first();

      if (this.options.backdrop) {
        backdrop.appendTo(this.options.container).hide();
      }
      _globalIdSeed++;
      if (this.getTrigger() === "sticky") {
        this.show();
      }

      if (this.options.selector) {
        this._options = $.extend({}, this.options, {
          selector: "",
        });
      }
    },
    /* api methods and actions */
    destroy: function () {
      var index = -1;

      for (var i = 0; i < _srcElements.length; i++) {
        if (_srcElements[i] === this.$element) {
          index = i;
          break;
        }
      }

      _srcElements.splice(index, 1);

      this.hide();
      this.$element.data("plugin_" + pluginName, null);
      if (this.getTrigger() === "click") {
        this.$element.off("click");
      } else if (this.getTrigger() === "hover") {
        this.$element.off("mouseenter mouseleave");
      }
      if (this.$target) {
        this.$target.remove();
      }
    },
    getDelegateOptions: function () {
      var options = {};

      this._options &&
        $.each(this._options, function (key, value) {
          if (defaults[key] !== value) {
            options[key] = value;
          }
        });
      return options;
    },
    /*
                    param: force    boolean value, if value is true then force hide the popover
                    param: event    dom event,
                */
    hide: function (force, event) {
      if (!force && this.getTrigger() === "sticky") {
        return;
      }
      if (!this._opened) {
        return;
      }
      if (event) {
        event.preventDefault();
        event.stopPropagation();
      }

      if (this.xhr && this.options.abortXHR === true) {
        this.xhr.abort();
        this.xhr = null;
      }

      var e = $.Event("hide." + pluginType);
      this.$element.trigger(e, [this.$target]);
      if (this.$target) {
        this.$target.removeClass("in").addClass(this.getHideAnimation());
        var that = this;
        setTimeout(function () {
          that.$target.hide();
          if (!that.getCache()) {
            that.$target.remove();
            //that.getTriggerElement.removeAttr('data-target');
          }
        }, that.getHideDelay());
      }
      if (this.options.backdrop) {
        backdrop.hide();
      }
      this._opened = false;
      this.$element.trigger("hidden." + pluginType, [this.$target]);

      if (this.options.onHide) {
        this.options.onHide(this.$target);
      }
    },
    resetAutoHide: function () {
      var that = this;
      var autoHide = that.getAutoHide();
      if (autoHide) {
        if (that.autoHideHandler) {
          clearTimeout(that.autoHideHandler);
        }
        that.autoHideHandler = setTimeout(function () {
          that.hide();
        }, autoHide);
      }
    },
    delegate: function (eventTarget) {
      var self = $(eventTarget).data("plugin_" + pluginName);
      if (!self) {
        self = new WebuiPopover(eventTarget, this.getDelegateOptions());
        $(eventTarget).data("plugin_" + pluginName, self);
      }
      return self;
    },
    toggle: function (e) {
      var self = this;
      if (e) {
        e.preventDefault();
        e.stopPropagation();
        if (this.options.selector) {
          self = this.delegate(e.currentTarget);
        }
      }
      self[self.getTarget().hasClass("in") ? "hide" : "show"]();
    },
    hideAll: function () {
      hideAllPop();
    },
    hideOthers: function () {
      hideOtherPops(this);
    },
    /*core method ,show popover */
    show: function () {
      if (this._opened) {
        return;
      }
      //removeAllTargets();
      var $target = this.getTarget()
        .removeClass()
        .addClass(pluginClass)
        .addClass(this._customTargetClass);
      if (!this.options.multi) {
        this.hideOthers();
      }

      // use cache by default, if not cache setted  , reInit the contents
      if (!this.getCache() || !this._poped || this.content === "") {
        this.content = "";
        this.setTitle(this.getTitle());
        if (!this.options.closeable) {
          $target.find(".close").off("click").remove();
        }
        if (!this.isAsync()) {
          this.setContent(this.getContent());
        } else {
          this.setContentASync(this.options.content);
        }

        if (this.canEmptyHide() && this.content === "") {
          return;
        }
        $target.show();
      }

      this.displayContent();

      if (this.options.onShow) {
        this.options.onShow($target);
      }

      this.bindBodyEvents();
      if (this.options.backdrop) {
        backdrop.show();
      }
      this._opened = true;
      this.resetAutoHide();
    },
    displayContent: function () {
      var //element postion
        elementPos = this.getElementPosition(),
        //target postion
        $target = this.getTarget()
          .removeClass()
          .addClass(pluginClass)
          .addClass(this._customTargetClass),
        //target content
        $targetContent = this.getContentElement(),
        //target Width
        targetWidth = $target[0].offsetWidth,
        //target Height
        targetHeight = $target[0].offsetHeight,
        //placement
        placement = "bottom",
        e = $.Event("show." + pluginType);

      if (this.canEmptyHide()) {
        var content = $targetContent.children().html();
        if (content !== null && content.trim().length === 0) {
          return;
        }
      }

      //if (this.hasContent()){
      this.$element.trigger(e, [$target]);
      //}
      // support width as data attribute
      var optWidth = this.$element.data("width") || this.options.width;
      if (optWidth === "") {
        optWidth = this._defaults.width;
      }

      if (optWidth !== "auto") {
        $target.width(optWidth);
      }

      // support height as data attribute
      var optHeight = this.$element.data("height") || this.options.height;
      if (optHeight === "") {
        optHeight = this._defaults.height;
      }

      if (optHeight !== "auto") {
        $targetContent.height(optHeight);
      }

      if (this.options.style) {
        this.$target.addClass(pluginClass + "-" + this.options.style);
      }

      //check rtl
      if (
        this.options.direction === "rtl" &&
        !$targetContent.hasClass(rtlClass)
      ) {
        $targetContent.addClass(rtlClass);
      }

      //init the popover and insert into the document body
      if (!this.options.arrow) {
        $target.find(".webui-arrow").remove();
      }
      $target.detach().css({
        top: _offsetOut,
        left: _offsetOut,
        display: "block",
        opacity: this.options.opacity || 1,
      });

      if (this.getAnimation()) {
        $target.addClass(this.getAnimation());
      }
      $target.appendTo(this.options.container);

      placement = this.getPlacement(elementPos);

      //This line is just for compatible with knockout custom binding
      this.$element.trigger("added." + pluginType);

      this.initTargetEvents();

      if (!this.options.padding) {
        if (this.options.height !== "auto") {
          $targetContent.css("height", $targetContent.outerHeight());
        }
        this.$target.addClass("webui-no-padding");
      }

      // add maxHeight and maxWidth support by limodou@gmail.com 2016/10/1
      if (this.options.maxHeight) {
        $targetContent.css("maxHeight", this.options.maxHeight);
      }

      if (this.options.maxWidth) {
        $targetContent.css("maxWidth", this.options.maxWidth);
      }
      // end

      targetWidth = $target[0].offsetWidth;
      targetHeight = $target[0].offsetHeight;

      var postionInfo = this.getTargetPositin(
        elementPos,
        placement,
        targetWidth,
        targetHeight
      );

      this.$target.css(postionInfo.position).addClass(placement).addClass("in");

      if (this.options.type === "iframe") {
        var $iframe = $target.find("iframe");
        var iframeWidth = $target.width();
        var iframeHeight = $iframe.parent().height();

        if (
          this.options.iframeOptions.width !== "" &&
          this.options.iframeOptions.width !== "auto"
        ) {
          iframeWidth = this.options.iframeOptions.width;
        }

        if (
          this.options.iframeOptions.height !== "" &&
          this.options.iframeOptions.height !== "auto"
        ) {
          iframeHeight = this.options.iframeOptions.height;
        }

        $iframe.width(iframeWidth).height(iframeHeight);
      }

      if (!this.options.arrow) {
        this.$target.css({
          margin: 0,
        });
      }
      if (this.options.arrow) {
        var $arrow = this.$target.find(".webui-arrow");
        $arrow.removeAttr("style");

        //prevent arrow change by content size
        if (placement === "left" || placement === "right") {
          $arrow.css({
            top: this.$target.height() / 2,
          });
        } else if (placement === "top" || placement === "bottom") {
          $arrow.css({
            left: this.$target.width() / 2,
          });
        }

        if (postionInfo.arrowOffset) {
          //hide the arrow if offset is negative
          if (
            postionInfo.arrowOffset.left === -1 ||
            postionInfo.arrowOffset.top === -1
          ) {
            $arrow.hide();
          } else {
            $arrow.css(postionInfo.arrowOffset);
          }
        }
      }
      this._poped = true;
      this.$element.trigger("shown." + pluginType, [this.$target]);
    },

    isTargetLoaded: function () {
      return this.getTarget().find("i.glyphicon-refresh").length === 0;
    },

    /*getter setters */
    getTriggerElement: function () {
      return this.$element;
    },
    getTarget: function () {
      if (!this.$target) {
        var id = pluginName + this._idSeed;
        this.$target = $(this.options.template).attr("id", id);
        this._customTargetClass =
          this.$target.attr("class") !== pluginClass
            ? this.$target.attr("class")
            : null;
        this.getTriggerElement().attr("data-target", id);
      }
      if (!this.$target.data("trigger-element")) {
        this.$target.data("trigger-element", this.getTriggerElement());
      }
      return this.$target;
    },
    removeTarget: function () {
      this.$target.remove();
      this.$target = null;
      this.$contentElement = null;
    },
    getTitleElement: function () {
      return this.getTarget().find("." + pluginClass + "-title");
    },
    getContentElement: function () {
      if (!this.$contentElement) {
        this.$contentElement = this.getTarget().find(
          "." + pluginClass + "-content"
        );
      }
      return this.$contentElement;
    },
    getTitle: function () {
      return (
        this.$element.attr("data-title") ||
        this.options.title ||
        this.$element.attr("title")
      );
    },
    getUrl: function () {
      return this.$element.attr("data-url") || this.options.url;
    },
    getAutoHide: function () {
      return this.$element.attr("data-auto-hide") || this.options.autoHide;
    },
    getOffsetTop: function () {
      return (
        toNumber(this.$element.attr("data-offset-top")) ||
        this.options.offsetTop
      );
    },
    getOffsetLeft: function () {
      return (
        toNumber(this.$element.attr("data-offset-left")) ||
        this.options.offsetLeft
      );
    },
    getCache: function () {
      var dataAttr = this.$element.attr("data-cache");
      if (typeof dataAttr !== "undefined") {
        switch (dataAttr.toLowerCase()) {
          case "true":
          case "yes":
          case "1":
            return true;
          case "false":
          case "no":
          case "0":
            return false;
        }
      }
      return this.options.cache;
    },
    getTrigger: function () {
      return this.$element.attr("data-trigger") || this.options.trigger;
    },
    getDelayShow: function () {
      var dataAttr = this.$element.attr("data-delay-show");
      if (typeof dataAttr !== "undefined") {
        return dataAttr;
      }
      return this.options.delay.show === 0 ? 0 : this.options.delay.show || 100;
    },
    getHideDelay: function () {
      var dataAttr = this.$element.attr("data-delay-hide");
      if (typeof dataAttr !== "undefined") {
        return dataAttr;
      }
      return this.options.delay.hide === 0 ? 0 : this.options.delay.hide || 100;
    },
    getAnimation: function () {
      var dataAttr = this.$element.attr("data-animation");
      return dataAttr || this.options.animation;
    },
    getHideAnimation: function () {
      var ani = this.getAnimation();
      return ani ? ani + "-out" : "out";
    },
    setTitle: function (title) {
      var $titleEl = this.getTitleElement();
      if (title) {
        //check rtl
        if (this.options.direction === "rtl" && !$titleEl.hasClass(rtlClass)) {
          $titleEl.addClass(rtlClass);
        }
        $titleEl.html(title);
      } else {
        $titleEl.remove();
      }
    },
    hasContent: function () {
      return this.getContent();
    },
    canEmptyHide: function () {
      return this.options.hideEmpty && this.options.type === "html";
    },
    getIframe: function () {
      var $iframe = $("<iframe></iframe>").attr("src", this.getUrl());
      var self = this;
      $.each(this._defaults.iframeOptions, function (opt) {
        if (typeof self.options.iframeOptions[opt] !== "undefined") {
          $iframe.attr(opt, self.options.iframeOptions[opt]);
        }
      });

      return $iframe;
    },
    getContent: function () {
      if (this.getUrl()) {
        switch (this.options.type) {
          case "iframe":
            this.content = this.getIframe();
            break;
          case "html":
            try {
              this.content = $(this.getUrl());
              if (!this.content.is(":visible")) {
                this.content.show();
              }
            } catch (error) {
              throw new Error(
                "Unable to get popover content. Invalid selector specified."
              );
            }
            break;
        }
      } else if (!this.content) {
        var content = "";
        if ($.isFunction(this.options.content)) {
          content = this.options.content.apply(this.$element[0], [this]);
        } else {
          content = this.options.content;
        }
        this.content = this.$element.attr("data-content") || content;
        if (!this.content) {
          var $next = this.$element.next();

          if ($next && $next.hasClass(pluginClass + "-content")) {
            this.content = $next;
          }
        }
      }
      return this.content;
    },
    setContent: function (content) {
      var $target = this.getTarget();
      var $ct = this.getContentElement();
      if (typeof content === "string") {
        $ct.html(content);
      } else if (content instanceof $) {
        $ct.html("");
        //Don't want to clone too many times.
        if (!this.options.cache) {
          content
            .clone(true, true)
            .removeClass(pluginClass + "-content")
            .appendTo($ct);
        } else {
          content.removeClass(pluginClass + "-content").appendTo($ct);
        }
      }
      this.$target = $target;
    },
    isAsync: function () {
      return this.options.type === "async";
    },
    setContentASync: function (content) {
      var that = this;
      if (this.xhr) {
        return;
      }
      this.xhr = $.ajax({
        url: this.getUrl(),
        type: this.options.async.type,
        cache: this.getCache(),
        beforeSend: function (xhr, settings) {
          if (that.options.async.before) {
            that.options.async.before(that, xhr, settings);
          }
        },
        success: function (data) {
          that.bindBodyEvents();
          if (content && $.isFunction(content)) {
            that.content = content.apply(that.$element[0], [data]);
          } else {
            that.content = data;
          }
          that.setContent(that.content);
          var $targetContent = that.getContentElement();
          $targetContent.removeAttr("style");
          that.displayContent();
          if (that.options.async.success) {
            that.options.async.success(that, data);
          }
        },
        complete: function () {
          that.xhr = null;
        },
        error: function (xhr, data) {
          if (that.options.async.error) {
            that.options.async.error(that, xhr, data);
          }
        },
      });
    },

    bindBodyEvents: function () {
      if (_isBodyEventHandled) {
        return;
      }
      if (this.options.dismissible && this.getTrigger() === "click") {
        if (isMobile) {
          $document
            .off("touchstart.webui-popover")
            .on(
              "touchstart.webui-popover",
              $.proxy(this.bodyTouchStartHandler, this)
            );
        } else {
          $document
            .off("keyup.webui-popover")
            .on("keyup.webui-popover", $.proxy(this.escapeHandler, this));
          $document
            .off("click.webui-popover")
            .on("click.webui-popover", $.proxy(this.bodyClickHandler, this));
        }
      } else if (this.getTrigger() === "hover") {
        $document
          .off("touchend.webui-popover")
          .on("touchend.webui-popover", $.proxy(this.bodyClickHandler, this));
      }
    },

    /* event handlers */
    mouseenterHandler: function (e) {
      var self = this;

      if (e && this.options.selector) {
        self = this.delegate(e.currentTarget);
      }

      if (self._timeout) {
        clearTimeout(self._timeout);
      }
      self._enterTimeout = setTimeout(function () {
        if (!self.getTarget().is(":visible")) {
          self.show();
        }
      }, this.getDelayShow());
    },
    mouseleaveHandler: function () {
      var self = this;
      clearTimeout(self._enterTimeout);
      //key point, set the _timeout  then use clearTimeout when mouse leave
      self._timeout = setTimeout(function () {
        self.hide();
      }, this.getHideDelay());
    },
    escapeHandler: function (e) {
      if (e.keyCode === 27) {
        this.hideAll();
      }
    },
    bodyTouchStartHandler: function (e) {
      var self = this;
      var $eventEl = $(e.currentTarget);
      $eventEl.on("touchend", function (e) {
        self.bodyClickHandler(e);
        $eventEl.off("touchend");
      });
      $eventEl.on("touchmove", function () {
        $eventEl.off("touchend");
      });
    },
    bodyClickHandler: function (e) {
      _isBodyEventHandled = true;
      var canHide = true;
      for (var i = 0; i < _srcElements.length; i++) {
        var pop = getPopFromElement(_srcElements[i]);
        if (pop && pop._opened) {
          var offset = pop.getTarget().offset();
          var popX1 = offset.left;
          var popY1 = offset.top;
          var popX2 = offset.left + pop.getTarget().width();
          var popY2 = offset.top + pop.getTarget().height();
          var pt = pointerEventToXY(e);
          var inPop =
            pt.x >= popX1 && pt.x <= popX2 && pt.y >= popY1 && pt.y <= popY2;
          if (inPop) {
            canHide = false;
            break;
          }
        }
      }
      if (canHide) {
        hideAllPop();
      }
    },

    /*
                targetClickHandler: function() {
                    this._targetclick = true;
                },
                */

    //reset and init the target events;
    initTargetEvents: function () {
      if (this.getTrigger() === "hover") {
        this.$target
          .off("mouseenter mouseleave")
          .on("mouseenter", $.proxy(this.mouseenterHandler, this))
          .on("mouseleave", $.proxy(this.mouseleaveHandler, this));
      }
      this.$target
        .find(".close")
        .off("click")
        .on("click", $.proxy(this.hide, this, true));
      //this.$target.off('click.webui-popover').on('click.webui-popover', $.proxy(this.targetClickHandler, this));
    },
    /* utils methods */
    //caculate placement of the popover
    getPlacement: function (pos) {
      var placement,
        container = this.options.container,
        clientWidth = container.innerWidth(),
        clientHeight = container.innerHeight(),
        scrollTop = container.scrollTop(),
        scrollLeft = container.scrollLeft(),
        pageX = Math.max(0, pos.left - scrollLeft),
        pageY = Math.max(0, pos.top - scrollTop);
      //arrowSize = 20;

      //if placement equals auto，caculate the placement by element information;
      if (typeof this.options.placement === "function") {
        placement = this.options.placement.call(
          this,
          this.getTarget()[0],
          this.$element[0]
        );
      } else {
        placement = this.$element.data("placement") || this.options.placement;
      }

      var isH = placement === "horizontal";
      var isV = placement === "vertical";
      var detect = placement === "auto" || isH || isV;

      if (detect) {
        if (pageX < clientWidth / 3) {
          if (pageY < clientHeight / 3) {
            placement = isH ? "right-bottom" : "bottom-right";
          } else if (pageY < (clientHeight * 2) / 3) {
            if (isV) {
              placement =
                pageY <= clientHeight / 2 ? "bottom-right" : "top-right";
            } else {
              placement = "right";
            }
          } else {
            placement = isH ? "right-top" : "top-right";
          }
          //placement= pageY>targetHeight+arrowSize?'top-right':'bottom-right';
        } else if (pageX < (clientWidth * 2) / 3) {
          if (pageY < clientHeight / 3) {
            if (isH) {
              placement =
                pageX <= clientWidth / 2 ? "right-bottom" : "left-bottom";
            } else {
              placement = "bottom";
            }
          } else if (pageY < (clientHeight * 2) / 3) {
            if (isH) {
              placement = pageX <= clientWidth / 2 ? "right" : "left";
            } else {
              placement = pageY <= clientHeight / 2 ? "bottom" : "top";
            }
          } else {
            if (isH) {
              placement = pageX <= clientWidth / 2 ? "right-top" : "left-top";
            } else {
              placement = "top";
            }
          }
        } else {
          //placement = pageY>targetHeight+arrowSize?'top-left':'bottom-left';
          if (pageY < clientHeight / 3) {
            placement = isH ? "left-bottom" : "bottom-left";
          } else if (pageY < (clientHeight * 2) / 3) {
            if (isV) {
              placement =
                pageY <= clientHeight / 2 ? "bottom-left" : "top-left";
            } else {
              placement = "left";
            }
          } else {
            placement = isH ? "left-top" : "top-left";
          }
        }
      } else if (placement === "auto-top") {
        if (pageX < clientWidth / 3) {
          placement = "top-right";
        } else if (pageX < (clientWidth * 2) / 3) {
          placement = "top";
        } else {
          placement = "top-left";
        }
      } else if (placement === "auto-bottom") {
        if (pageX < clientWidth / 3) {
          placement = "bottom-right";
        } else if (pageX < (clientWidth * 2) / 3) {
          placement = "bottom";
        } else {
          placement = "bottom-left";
        }
      } else if (placement === "auto-left") {
        if (pageY < clientHeight / 3) {
          placement = "left-top";
        } else if (pageY < (clientHeight * 2) / 3) {
          placement = "left";
        } else {
          placement = "left-bottom";
        }
      } else if (placement === "auto-right") {
        if (pageY < clientHeight / 3) {
          placement = "right-bottom";
        } else if (pageY < (clientHeight * 2) / 3) {
          placement = "right";
        } else {
          placement = "right-top";
        }
      }
      return placement;
    },
    getElementPosition: function () {
      // If the container is the body or normal conatiner, just use $element.offset()
      var elRect = this.$element[0].getBoundingClientRect();
      var container = this.options.container;
      var cssPos = container.css("position");

      if (container.is(document.body) || cssPos === "static") {
        return $.extend({}, this.$element.offset(), {
          width: this.$element[0].offsetWidth || elRect.width,
          height: this.$element[0].offsetHeight || elRect.height,
        });
        // Else fixed container need recalculate the  position
      } else if (cssPos === "fixed") {
        var containerRect = container[0].getBoundingClientRect();
        return {
          top: elRect.top - containerRect.top + container.scrollTop(),
          left: elRect.left - containerRect.left + container.scrollLeft(),
          width: elRect.width,
          height: elRect.height,
        };
      } else if (cssPos === "relative") {
        return {
          top: this.$element.offset().top - container.offset().top,
          left: this.$element.offset().left - container.offset().left,
          width: this.$element[0].offsetWidth || elRect.width,
          height: this.$element[0].offsetHeight || elRect.height,
        };
      }
    },

    getTargetPositin: function (
      elementPos,
      placement,
      targetWidth,
      targetHeight
    ) {
      var pos = elementPos,
        container = this.options.container,
        //clientWidth = container.innerWidth(),
        //clientHeight = container.innerHeight(),
        elementW = this.$element.outerWidth(),
        elementH = this.$element.outerHeight(),
        scrollTop = document.documentElement.scrollTop + container.scrollTop(),
        scrollLeft =
          document.documentElement.scrollLeft + container.scrollLeft(),
        position = {},
        arrowOffset = null,
        arrowSize = this.options.arrow ? 20 : 0,
        padding = 10,
        fixedW = elementW < arrowSize + padding ? arrowSize : 0,
        fixedH = elementH < arrowSize + padding ? arrowSize : 0,
        refix = 0,
        pageH = document.documentElement.clientHeight + scrollTop,
        pageW = document.documentElement.clientWidth + scrollLeft;

      var validLeft = pos.left + pos.width / 2 - fixedW > 0;
      var validRight = pos.left + pos.width / 2 + fixedW < pageW;
      var validTop = pos.top + pos.height / 2 - fixedH > 0;
      var validBottom = pos.top + pos.height / 2 + fixedH < pageH;

      switch (placement) {
        case "bottom":
          position = {
            top: pos.top + pos.height,
            left: pos.left + pos.width / 2 - targetWidth / 2,
          };
          break;
        case "top":
          position = {
            top: pos.top - targetHeight,
            left: pos.left + pos.width / 2 - targetWidth / 2,
          };
          break;
        case "left":
          position = {
            top: pos.top + pos.height / 2 - targetHeight / 2,
            left: pos.left - targetWidth,
          };
          break;
        case "right":
          position = {
            top: pos.top + pos.height / 2 - targetHeight / 2,
            left: pos.left + pos.width,
          };
          break;
        case "top-right":
          position = {
            top: pos.top - targetHeight,
            left: validLeft ? pos.left - fixedW : padding,
          };
          arrowOffset = {
            left: validLeft
              ? Math.min(elementW, targetWidth) / 2 + fixedW
              : _offsetOut,
          };
          break;
        case "top-left":
          refix = validRight ? fixedW : -padding;
          position = {
            top: pos.top - targetHeight,
            left: pos.left - targetWidth + pos.width + refix,
          };
          arrowOffset = {
            left: validRight
              ? targetWidth - Math.min(elementW, targetWidth) / 2 - fixedW
              : _offsetOut,
          };
          break;
        case "bottom-right":
          position = {
            top: pos.top + pos.height,
            left: validLeft ? pos.left - fixedW : padding,
          };
          arrowOffset = {
            left: validLeft
              ? Math.min(elementW, targetWidth) / 2 + fixedW
              : _offsetOut,
          };
          break;
        case "bottom-left":
          refix = validRight ? fixedW : -padding;
          position = {
            top: pos.top + pos.height,
            left: pos.left - targetWidth + pos.width + refix,
          };
          arrowOffset = {
            left: validRight
              ? targetWidth - Math.min(elementW, targetWidth) / 2 - fixedW
              : _offsetOut,
          };
          break;
        case "right-top":
          refix = validBottom ? fixedH : -padding;
          position = {
            top: pos.top - targetHeight + pos.height + refix,
            left: pos.left + pos.width,
          };
          arrowOffset = {
            top: validBottom
              ? targetHeight - Math.min(elementH, targetHeight) / 2 - fixedH
              : _offsetOut,
          };
          break;
        case "right-bottom":
          position = {
            top: validTop ? pos.top - fixedH : padding,
            left: pos.left + pos.width,
          };
          arrowOffset = {
            top: validTop
              ? Math.min(elementH, targetHeight) / 2 + fixedH
              : _offsetOut,
          };
          break;
        case "left-top":
          refix = validBottom ? fixedH : -padding;
          position = {
            top: pos.top - targetHeight + pos.height + refix,
            left: pos.left - targetWidth,
          };
          arrowOffset = {
            top: validBottom
              ? targetHeight - Math.min(elementH, targetHeight) / 2 - fixedH
              : _offsetOut,
          };
          break;
        case "left-bottom":
          position = {
            top: validTop ? pos.top - fixedH : padding,
            left: pos.left - targetWidth,
          };
          arrowOffset = {
            top: validTop
              ? Math.min(elementH, targetHeight) / 2 + fixedH
              : _offsetOut,
          };
          break;
      }
      position.top += this.getOffsetTop();
      position.left += this.getOffsetLeft();

      return {
        position: position,
        arrowOffset: arrowOffset,
      };
    },
  };
  $.fn[pluginName] = function (options, noInit) {
    var results = [];
    var $result = this.each(function () {
      var webuiPopover = $.data(this, "plugin_" + pluginName);
      if (!webuiPopover) {
        if (!options) {
          webuiPopover = new WebuiPopover(this, null);
        } else if (typeof options === "string") {
          if (options !== "destroy") {
            if (!noInit) {
              webuiPopover = new WebuiPopover(this, null);
              results.push(webuiPopover[options]());
            }
          }
        } else if (typeof options === "object") {
          webuiPopover = new WebuiPopover(this, options);
        }
        $.data(this, "plugin_" + pluginName, webuiPopover);
      } else {
        if (options === "destroy") {
          webuiPopover.destroy();
        } else if (typeof options === "string") {
          results.push(webuiPopover[options]());
        }
      }
    });
    return results.length ? results : $result;
  };

  //Global object exposes to window.
  var webuiPopovers = (function () {
    var _hideAll = function () {
      hideAllPop();
    };
    var _create = function (selector, options) {
      options = options || {};
      $(selector).webuiPopover(options);
    };
    var _isCreated = function (selector) {
      var created = true;
      $(selector).each(function (i, item) {
        created = created && $(item).data("plugin_" + pluginName) !== undefined;
      });
      return created;
    };
    var _show = function (selector, options) {
      if (options) {
        $(selector).webuiPopover(options).webuiPopover("show");
      } else {
        $(selector).webuiPopover("show");
      }
    };
    var _hide = function (selector) {
      $(selector).webuiPopover("hide");
    };

    var _setDefaultOptions = function (options) {
      defaults = $.extend({}, defaults, options);
    };

    var _updateContent = function (selector, content) {
      var pop = $(selector).data("plugin_" + pluginName);
      if (pop) {
        var cache = pop.getCache();
        pop.options.cache = false;
        pop.options.content = content;
        if (pop._opened) {
          pop._opened = false;
          pop.show();
        } else {
          if (pop.isAsync()) {
            pop.setContentASync(content);
          } else {
            pop.setContent(content);
          }
        }
        pop.options.cache = cache;
      }
    };

    var _updateContentAsync = function (selector, url) {
      var pop = $(selector).data("plugin_" + pluginName);
      if (pop) {
        var cache = pop.getCache();
        var type = pop.options.type;
        pop.options.cache = false;
        pop.options.url = url;

        if (pop._opened) {
          pop._opened = false;
          pop.show();
        } else {
          pop.options.type = "async";
          pop.setContentASync(pop.content);
        }
        pop.options.cache = cache;
        pop.options.type = type;
      }
    };

    return {
      show: _show,
      hide: _hide,
      create: _create,
      isCreated: _isCreated,
      hideAll: _hideAll,
      updateContent: _updateContent,
      updateContentAsync: _updateContentAsync,
      setDefaultOptions: _setDefaultOptions,
    };
  })();
  window.WebuiPopovers = webuiPopovers;
  layui.link(layui.cache.base + "popover/popover.css");
  exports("popover", WebuiPopovers);
});
